package com.hsxc.cdz.monitor.FSM;

import com.hsxc.cdz.base.bean.Pile;
import com.hsxc.cdz.base.dao.PileDao;
import com.hsxc.cdz.base.util.ApplicationUtil;
import com.hsxc.cdz.mgmt.GlobalManager;
import com.hsxc.cdz.trans.bill.CacheTrade;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class PileMemState {
    private Logger logger = LoggerFactory.getLogger(PileMemState.class);

    public enum Status {
        PILE_STATUS_IDLE, // 空闲 0
        PILE_STATUS_FAULT, // 故障 1
        PILE_STATUS_RESERVED, // 预约中 2
        PILE_STATUS_LOCKED, // 锁定中 3
        PILE_STATUS_CHARGING, // 充电中 4
        PILE_STATUS_ABNORMAL_OFFLINE,// 异常离线 5
    }

    ;

    // 成员变量
    protected Status status;
    protected CachePile pile;

    private PileDao pileDao = (PileDao) ApplicationUtil.getBean("pileDao");
    // ===========================================================================
    // 构造函数
    /*
	 * public void PileMemState(CachePile pile) { this.pile = pile; this.status
	 * = Status.PILE_STATUS_IDLE; }
	 */

    public static int Transimit() {
        return 0;
    }

    // ===========================================================================
    // 故障
    abstract int fault();

    // 故障恢复
    abstract int recovery();

    public abstract int reboot();

    /**
     * 交流桩的启动充电方法
     *
     * @param chargePort
     * @param startWay
     * @param ctrlWay     控制数据
     * @param stopWay     停止方法
     * @param limitData   县直属局
     * @param startTime   开始时间
     * @param cardNum     卡号
     * @param pileAddress 桩号
     * @param operatorNO  运营商号
     * @return SUCCESS 0 FAIL 1
     */
    public abstract int chargeStart_jiaoliu(int chargePort, int startWay, int ctrlWay, int stopWay, double limitData,
                                            String startTime, String cardNum, String pileAddress, String operatorNO, String protocol, int pileType);

    /**
     * 直流桩的开启充电方法
     *
     * @param chargePort
     * @param startWay
     * @param ctrlWay
     * @param stopWay
     * @param limitData
     * @param startTime
     * @param cardNum
     * @param pileAddress
     * @param operatorNO
     * @param chargeDataInterval 充电数据上传间隔 单位：秒
     * @param batteryDataInteval 电池信息上传间隔 单位： 秒
     * @return SUCCESS 0 FAIL 1
     */
    public abstract int chargeStart_zhiliu(int chargePort, int startWay, int ctrlWay, int stopWay, double limitData,
                                           String startTime, String cardNum, String pileAddress, String operatorNO, int chargeDataInterval,
                                           int batteryDataInteval, String protocol, int pileType);

    /**
     * 确认开始充电 两种桩协议相同，共用一种方法
     *
     * @param pileNo
     * @param userNo
     * @return
     */
    public abstract boolean confirmStart(int chargePort, String pileNo, String userNo, String protocol, int pileType);

    /**
     * 停止充电 两种桩协议相同，共用一种方法
     *
     * @param userNO
     * @return
     */
    public abstract int chargeStop(int chargePort, int control, String userNO, String protocol, int pileType);

    /**
     * 确认停止充电 两种桩协议相同，共用一种方法
     *
     * @param pileNo
     * @param userNo
     * @return
     */
    public abstract boolean confirmStop(int chargePort, String pileNo, String userNo, String protocol, int pileType);
    // 预约
    /**
     * 直流电桩电桩预约操作--启动方法
     *
     * @param chargePort
     *            被预约的端口号
     * @param cardNum
     *            用户卡号即用户手机号
     * @param duration
     *            预约时长
     * @param pileAddress
     *            电桩地址
     * @param operatorNo
     *            运营商编号
     * @return 成功--0 失败--1
     */
    // abstract int reserve_zhiliu(int chargePort, String cardNum, int duration,
    // String pileAddress, String operatorNo,
    // String protocol);

    /**
     * 电桩预约--启动方法，共用一个方法
     *
     * @param chargePort
     * @param cardNo
     * @param pileAddress
     * @param operatorNo
     * @return
     */
    abstract int reserve(int chargePort, String cardNo, int duration, String pileAddress, String operatorNo,
                         String protocol, int pileType);

    /**
     * 交流电桩主动回复确认预约成功
     * 交流桩可以不用确认
     *
     * @param chargePort
     * @param cardNo
     * @param pileAddress
     * @param operator
     * @return
     */
    abstract int confirmReserv_jiaoliu(int chargePort, String cardNo, String pileAddress, String operator,
                                       String protocol, int pileType);

    /**
     * 直流电桩主动回复确认预约成功
     *
     * @param chargePort
     * @param cardNo
     * @param pileAddress
     * @param operator
     * @return
     */
    abstract int confirmReserv_zhiliu(int chargePort, String cardNo, String resStartTime, String pileAddress, String operator,
                                      String protocol, int pileType);

    // 取消预约

    /**
     * to cancel a reservation 两种协议共用
     *
     * @param cardNum    用户卡号即用户手机号
     * @param pileadress 电桩地址
     * @param chargePort 充电口号
     * @return SUCCESS 0 FAIL 1
     */
    abstract int reservationCancel(int chargePort, String cardNum, String pileadress, String operatorNo,
                                   String protocol, int pileType);

    /**
     * 确认预约取消
     *
     * @param cardNum
     * @param port
     * @return SUCCESS 0 FAIL 1
     */
    // abstract int confirmReservCancelled_jiaoliu(String cardNum, int
    // port,String protocol,int pileType);

    /**
     * 交流桩确认取消充电
     *
     * @param chargePort
     * @param cardNo
     * @param pileAddress
     * @param operatorNo
     * @return
     */
    abstract int confirmReservCancelled(int chargePort, String cardNo, String pileAddress, String operatorNo,
                                        String protocol, int pileType);

    // 锁定
    abstract int lock();

    // 解除锁定
    abstract int unlock();

    // 心跳丢失
    abstract int heartBeatLost();

    /**
     * 退出登录
     *
     * @return ：是否成功 1 失败，0 成功
     */
    public abstract int logout();

    public int updatePileStatus(CachePile cachePile) {
        Pile pile = new Pile();
        pile.setPileNO(cachePile.getAddress());
        switch (cachePile.getStatus()) {
            case PILE_STATUS_ABNORMAL_OFFLINE:
                pile.setState(Pile.STATE_OFFLINE);
                break;
            case PILE_STATUS_CHARGING:
                pile.setState(Pile.STATE_CHARGING);
                break;
            case PILE_STATUS_FAULT:
                pile.setState(Pile.STATE_FALUT);
                break;
            case PILE_STATUS_IDLE:
                pile.setState(Pile.STATE_IDLE);
                break;
            case PILE_STATUS_LOCKED:
                pile.setState(Pile.STATE_LOCKED);
                break;
            case PILE_STATUS_RESERVED:
                pile.setState(Pile.STATE_RESERVED);
                break;
            default:
                break;
        }
        return pileDao.updatePile(pile);
    }

    // 异常离线
    public boolean offLine() {
        logger.info("心跳丢失离线处理");
        CacheTrade cacheTrade = GlobalManager.tradeManager.getTradeByPileAddress(this.pile.getAddress());
        if (cacheTrade == null) {
            logger.info("离线时，不存在交易，remove from cache" + this.pile.getStatus());
            this.pile.state = new PileMemStateOffline(this.pile);
            GlobalManager.pileManager.delPile(this.pile.getAddress());
        }
        this.updatePileStatus(this.pile);
        return true;
    }

    public void changeStateCharge() {
        if (this.status != Status.PILE_STATUS_CHARGING) {
            this.pile.state = new PileMemStateCharging(this.pile);
            this.updatePileStatus(this.pile);
        }
    }

    public void changeStateIdle() {
        if (this.status != Status.PILE_STATUS_IDLE) {
            this.pile.state = new PileMemStateIdle(this.pile);
            this.updatePileStatus(this.pile);
        }
    }

    public void changeStateReservd() {
        if (this.status != Status.PILE_STATUS_RESERVED) {
            this.pile.state = new PileMemStateReserved(this.pile);
            this.updatePileStatus(this.pile);
        }
    }

    public void changeStateLocked() {
        if (this.status != Status.PILE_STATUS_LOCKED) {
            this.pile.state = new PileMemStateLocked(this.pile);
            this.updatePileStatus(this.pile);
        }
    }

}
